import struct
import socket
from PIL import ImageGrab
from cv2 import cv2
import numpy as np
import threading

bufsize = 1024

host = ('0.0.0.0', 80)
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.bind(host)
soc.listen(1)
img = None

def handle(conn):
    global img

    # 1. 发送第一张图片
    # 截图， 转换为 numpy 的数组
    img = np.asarray(ImageGrab.grab())
    # 转换成字节码 png 无损压缩的格式
    _, imb = cv2.imencode(".png", img)
    # 将数据打包为 无符号整型 4 字节
    lenb = struct.pack(">I", len(imb))

    # 发送 数据长度
    conn.sendall(lenb)
    # 发送数据
    conn.sendall(imb)

    # 2. 发送 差异化图像
    while True:
        # 刷新率
        cv2.waitKey(1)
        # 截图
        gb = ImageGrab.grab()
        # 将截图转换成 numpy 数组
        imgnpn = np.asarray(gb)
        # 获取 差异化数据
        subn = imgnpn - img
        # 如果没变化， 下一轮循环
        if (subn == 0).all():
            continue
        # 保存下差异化数据
        img = imgnpn
        """
            cv2.imdecode() 
                函数从指定内存缓存中读取数据，将数据转换(解码)成图像格式，用于从网络传输数据中恢复出图像

            cv2.imencode()
                函数将图像格式转换(编码)成流数据，赋值到内存缓存中，主要用于图像数据格式压缩，方便网络传输
        """
        # 将图像转换为数据
        _, imb = cv2.imencode(".png", subn)
        # 获取数据长度
        dlen = len(imb)
        # 将数据转换为 无符号整型 4字节
        lenb = struct.pack(">I", dlen)
        try:
            # 发送数据
            conn.sendall(lenb)
            conn.sendall(imb)
        except:
            print("连接中断....")
            return


while True:
    # socket 连接
    conn, addr = soc.accept()
    # 创建一个线程, 并启动
    threading.Thread(target=handle, args=(conn,)).start()